package stateDiagram.figures;

import static org.jhotdraw.draw.AttributeKeys.FILL_COLOR;
import static org.jhotdraw.draw.AttributeKeys.FONT_BOLD;
import static org.jhotdraw.draw.AttributeKeys.STROKE_COLOR;
import static org.jhotdraw.draw.AttributeKeys.STROKE_DASHES;

import java.awt.Color;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.swing.Action;

import org.jhotdraw.app.action.edit.AddInternalTransitionAction;
import org.jhotdraw.app.action.edit.RemoveInternalTransitionAction;
import org.jhotdraw.draw.ListFigure;
import org.jhotdraw.draw.RoundRectangleFigure;
import org.jhotdraw.draw.TextFigure;
import org.jhotdraw.draw.layouter.VerticalLayouter;
import org.jhotdraw.geom.Insets2D;
import org.jhotdraw.util.ResourceBundleUtil;
import org.jhotdraw.xml.DOMInput;
import org.jhotdraw.xml.DOMOutput;

import stateDiagram.EntityObjects.StateEntity;
import stateDiagram.EntityObjects.SubStateEntity;
import stateDiagram.EntityObjects.SuperStateEntity;

public class SubStateFigure extends StateFigure{

	/**
	 * default serial ID
	 */
	private static final long serialVersionUID = 1L;

	SuperStateFigure _parentFigure;
	SuperStateEntity _parentEntity; //needed?
	private HashSet<TransitionFigure> transitions; //transitions involving this substatefigure
	private SubStateEntity subStateEntity;
	
    
	 /** Creates a new instance. */
    public SubStateFigure() {
        super(Color.BLUE);
        
        subStateEntity = new SubStateEntity("State","Event","Action");

        setLayouter(new VerticalLayouter());
        RoundRectangleFigure nameCompartmentPF = new RoundRectangleFigure();
        nameCompartmentPF.set(STROKE_COLOR, Color.BLUE);
        nameCompartmentPF.setAttributeEnabled(STROKE_COLOR, true);
        //nameCompartmentPF.set(CANVAS_FILL_COLOR, Color.BLUE);
        //nameCompartmentPF.setAttributeEnabled(CANVAS_FILL_COLOR, true);
        nameCompartmentPF.set(FILL_COLOR, Color.BLUE);
        nameCompartmentPF.setAttributeEnabled(FILL_COLOR, true);
        ListFigure nameCompartment = new ListFigure(nameCompartmentPF);
        nameCompartment.setAttributeEnabled(FILL_COLOR,true);
        nameCompartment.set(FILL_COLOR,Color.BLUE);
        ListFigure subExitAttributeCompartment = new ListFigure();
        ListFigure subDynamicAttributeCompartment = new ListFigure();
        ListFigure subEntryAttributeCompartment = new ListFigure();
        ListFigure subAllEventContainer = new ListFigure();
       
        //attributeCompartment.setAttributeEnabled(FILL_COLOR,true);
        //attributeCompartment.set(FILL_COLOR,Color.RED);
        SeperatorFigure separator1 = new SeperatorFigure();

        add(nameCompartment);
        add(separator1);
       // add(attributeCompartment);
        add(subAllEventContainer);
        
        Insets2D.Double insets = new Insets2D.Double(20, 20, 20, 20);
        nameCompartment.set(LAYOUT_INSETS, insets);
        //attributeCompartment.set(LAYOUT_INSETS, insets);

        StateNameTextFigure nameFigure;
        nameCompartment.add(nameFigure = new StateNameTextFigure(this.getStateEntity()));
        nameFigure.set(FONT_BOLD, true);
        nameFigure.setAttributeEnabled(FONT_BOLD, false);

        TextFigure EntryEventTextFigure;
        subEntryAttributeCompartment.add(EntryEventTextFigure = new TextFigure());
        EntryEventTextFigure.setEditable(false);
        EntryEventTextFigure.setText("Entry/");
        EntryEventTextFigure.setAttributeEnabled(FONT_BOLD, false);
        
        EntryActionTextFigure entryActionTextFigure;
        subEntryAttributeCompartment.add(entryActionTextFigure = new EntryActionTextFigure((StateEntity)this.getStateEntity()));
        entryActionTextFigure.setEditable(true);
        entryActionTextFigure.setText("add Entry action here");;
        entryActionTextFigure.setAttributeEnabled(FONT_BOLD, false);
        
        TextFigure exitEventTextFigure;
        subExitAttributeCompartment.add(exitEventTextFigure = new TextFigure());
        exitEventTextFigure.setEditable(false);
        exitEventTextFigure.setText("Exit/");
        exitEventTextFigure.setAttributeEnabled(FONT_BOLD, false);
        
        TextFigure exitActionTextFigure;
        subExitAttributeCompartment.add(exitActionTextFigure = new ExitActionTextFigure(this.getStateEntity()));
        exitActionTextFigure.setEditable(true);
        exitActionTextFigure.setText("add exit action here");
        exitActionTextFigure.setAttributeEnabled(FONT_BOLD, false);

        setAttributeEnabled(STROKE_DASHES, false);
        
        subAllEventContainer.add(subEntryAttributeCompartment);
        subAllEventContainer.add(subDynamicAttributeCompartment);
        subAllEventContainer.add(subExitAttributeCompartment);

        ResourceBundleUtil labels =
                ResourceBundleUtil.getBundle("org.jhotdraw.samples.pert.Labels");
        
        // instantiate a new Entity to store this figures data -james
        //need to be able to update entities as user changes labels in figure.
        
        
        subStateEntity.setStateFigure(this);
        setName(labels.getString("State"));
        setExit("add exit action");
        setEntry("add entry action");

    }
    public SubStateEntity getStateEntity() {
		return subStateEntity;
	}
    public void setParentFigure( SuperStateFigure fig){
    	_parentFigure = fig;
    }
    
	public void setName(String newValue) {
        getNameFigure().setText(newValue);
    }

    public String getName() {
        return getNameFigure().getText();
    }

    public StateNameTextFigure getNameFigure() {
        return (StateNameTextFigure) ((ListFigure) getChild(0)).getChild(0);
    }
    
    public TextFigure getEntryFigure() {
        ListFigure entryfig = (ListFigure) ((ListFigure) getChild(2)).getChild(0);
        return (TextFigure) entryfig.getChild(1);
    }
    
    public void setEntry(String newValue) {
        getEntryFigure().setText(newValue);
    }
    
    public TextFigure getExitFigure() {
      ListFigure ExitFig = getExitContainer();
      return (TextFigure) ExitFig.getChild(1);
       
    }
    
    private ListFigure getExitContainer(){
    	return (ListFigure) ( (ListFigure) getChild(2)).getChild(2);
    }
    
    public void setExit(String newValue) {
        getExitFigure().setText(newValue);
    }
    
    private ListFigure getDynamicContainer(){
    	return (ListFigure) ( (ListFigure) getChild(2)).getChild(1);
    }
    
    @Override
    public SubStateFigure clone() {
        SubStateFigure that = new SubStateFigure();
     
        that.transitions = new HashSet<TransitionFigure>();
        return that;
    }
    
    //////////////methods for transition figure to check parent status/////////////////////
    public boolean hasAParent(){
    	if (_parentFigure == null){
    		return false;
    	}
    	else{
    		return true;
    	}
    }
    public String getParentName(){
    	return _parentFigure.getStateEntity().getName();
    }
    public SuperStateFigure getParentFigure(){
    	return _parentFigure;
    }
    
    //override getActions()-james
    public Collection<Action> getActions(Point2D.Double p) {
    	Collection<Action> popupMenu = new ArrayList<Action>();
    	  popupMenu.add(new AddInternalTransitionAction(null, this));
    	  
    	 
    	int index = getDynamicContainer().findChildIndex(p); 
    	if (index != -1){
    		popupMenu.add(new RemoveInternalTransitionAction(null, this, index));
    	}
    return popupMenu;
    }
    public void addInternalTransition(String eventName, String actionName ){
    	
   	 willChange();
   	 //add a new event action pair to the dynamic Container
     getDynamicContainer().add(new InternalTransitionFigure(eventName, actionName, getStateEntity()));
 
   	 changed();	
   }
   
   public void removeInternalTransition(int index){
   	System.out.println("I got called");
   	willChange();
   	getDynamicContainer().basicRemoveChild(index);
   	changed();
   	
   	
   }
   
   public int getLayer() {
       return 0;
   }

   public Set<TransitionFigure> getDependencies() {
       return Collections.unmodifiableSet(transitions);
   }

   public void addDependency(TransitionFigure f) {
       transitions.add(f);

   }

   public void removeDependency(TransitionFigure f) {
       transitions.remove(f);

   }

   /**
    * Returns dependent StateFigures which are directly connected via a
    * transition to this StateFigure.
    */
   public List<StateFigure> getSuccessors() {
       LinkedList<StateFigure> list = new LinkedList<StateFigure>();
       for (TransitionFigure c : getDependencies()) {
           if (c.getStartFigure() == this) {
               list.add((StateFigure) c.getEndFigure());
           }

       }
       return list;
   }

   /**
    * Returns predecessor StateFigures which are directly connected via a
    * transition to this StateFigure.
    */
   public List<StateFigure> getPredecessors() {
       LinkedList<StateFigure> list = new LinkedList<StateFigure>();
       for (TransitionFigure c : getDependencies()) {
           if (c.getEndFigure() == this && c.getStartFigure() instanceof StateFigure) {
               list.add((StateFigure) c.getStartFigure());
           }

       }
       return list;
   }

   /**
    * Returns true, if the current task is a direct or
    * indirect dependent of the specified task.
    * If the dependency is cyclic, then this method returns true
    * if <code>this</code> is passed as a parameter and for every other
    * task in the cycle.
    */
   public boolean isDependentOf(StateFigure t) {
       if (this == t) {
           return true;
       }

       for (StateFigure pre : getPredecessors()) {
           if (pre.isDependentOf(t)) {
               return true;
           }

       }
       return false;
   }
   
 
}
